<?php

// view_log.php - 统一 MySQL 日志查看器

require_once 'db_config.php'; // 引入数据库配置

define('ITEMS_PER_PAGE', 20); // 每页显示的日志条目数量

// 从 GET 参数获取过滤器
$domainFilter = isset($_GET['domain']) ? htmlspecialchars(trim($_GET['domain'])) : '';
$statusCodeFilter = isset($_GET['status_code']) ? htmlspecialchars(trim($_GET['status_code'])) : ''; // 新增状态码过滤器
$startDate = isset($_GET['start_date']) ? htmlspecialchars($_GET['start_date']) : '';
$endDate = isset($_GET['end_date']) ? htmlspecialchars($_GET['end_date']) : '';
$currentPage = isset($_GET['page']) ? (int)$_GET['page'] : 1;
if ($currentPage < 1) $currentPage = 1;

$logs = [];
$totalLogs = 0;
$totalPages = 1;

$conn = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
if ($conn->connect_error) {
    die("MySQL 连接失败: " . $conn->connect_error);
}

// 构建 WHERE 子句用于过滤
$whereClauses = [];
$params = [];
$paramTypes = "";

if (!empty($domainFilter)) {
    $whereClauses[] = "url LIKE ?";
    $params[] = "%" . $domainFilter . "%";
    $paramTypes .= "s";
}
if (!empty($statusCodeFilter)) {
    // 允许逗号分隔的状态码，例如 "200,404"
    $statusCodes = array_map('trim', explode(',', $statusCodeFilter));
    $placeholders = implode(',', array_fill(0, count($statusCodes), '?'));
    $whereClauses[] = "status_code IN (" . $placeholders . ")";
    foreach ($statusCodes as $code) {
        $params[] = $code;
        $paramTypes .= "s";
    }
}
if (!empty($startDate)) {
    $whereClauses[] = "log_time >= ?";
    $params[] = $startDate . " 00:00:00";
    $paramTypes .= "s";
}
if (!empty($endDate)) {
    $whereClauses[] = "log_time <= ?";
    $params[] = $endDate . " 23:59:59";
    $paramTypes .= "s";
}

$whereSql = "";
if (!empty($whereClauses)) {
    $whereSql = " WHERE " . implode(" AND ", $whereClauses);
}

// 获取总记录数用于分页
$countSql = "SELECT COUNT(*) FROM monitor_logs" . $whereSql;
$stmtCount = $conn->prepare($countSql);

// 动态绑定计数查询的参数
if (!empty($params)) {
    // 使用 call_user_func_array 来绑定数组参数
    call_user_func_array([$stmtCount, 'bind_param'], array_merge([$paramTypes], refValues($params)));
}
$stmtCount->execute();
$stmtCount->bind_result($totalLogs);
$stmtCount->fetch();
$stmtCount->close();

$totalPages = ceil($totalLogs / ITEMS_PER_PAGE);
$offset = ($currentPage - 1) * ITEMS_PER_PAGE;

// 获取实际的日志数据
$sql = "SELECT id, url, status_code, status_message, response_time, log_time, details FROM monitor_logs"
    . $whereSql . " ORDER BY log_time DESC LIMIT ?, ?";
$stmt = $conn->prepare($sql);

// 重新准备主查询的参数，包括 LIMIT 和 OFFSET
$mainQueryParams = $params; // 从过滤器参数开始
$mainParamTypes = $paramTypes; // 从过滤器参数类型开始

$mainParamTypes .= "ii"; // 添加 LIMIT 和 OFFSET 的类型
$mainQueryParams[] = $offset;
$mainQueryParams[] = ITEMS_PER_PAGE;

// 动态绑定主查询的参数
if (!empty($mainQueryParams)) {
    @call_user_func_array([$stmt, 'bind_param'], array_merge([$mainParamTypes], refValues($mainQueryParams)));
}

$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
    $logs[] = $row;
}
$stmt->close();
$conn->close();

// 辅助函数，用于 call_user_func_array 绑定参数时需要引用
function refValues($arr){
    if (strnatcmp(phpversion(),'5.3') >= 0) // PHP 5.3+ 需要引用
    {
        $refs = array();
        foreach($arr as $key => $value)
            $refs[$key] = &$arr[$key];
        return $refs;
    }
    return $arr;
}

?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>监控日志 - MySQL</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; background-color: #f4f4f4; color: #333; }
        .container { max-width: 1400px; margin: auto; background: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
        h1 { color: #0056b3; }
        .back-link { margin-bottom: 20px; text-align: left; }
        .back-link a { color: #007bff; text-decoration: none; }
        .back-link a:hover { text-decoration: underline; }

        /* 筛选表单样式优化 */
        .filter-form {
            margin-bottom: 20px;
            padding: 15px;
            border: 1px solid #ddd;
            border-radius: 5px;
            background-color: #f9f9f9;
            display: flex; /* 使用 Flexbox */
            flex-wrap: wrap; /* 允许换行 */
            gap: 15px; /* 增加间距 */
            align-items: flex-end; /* 底部对齐 */
        }
        .filter-form div {
            flex: 1; /* 弹性伸缩 */
            min-width: 180px; /* 最小宽度，防止太窄 */
        }
        .filter-form label {
            font-weight: bold;
            margin-bottom: 5px;
            display: block;
            color: #555;
        }
        .filter-form input[type="date"],
        .filter-form input[type="text"] {
            width: 100%;
            padding: 8px;
            border: 1px solid #ccc; /* 边框颜色稍深 */
            border-radius: 4px;
            box-sizing: border-box;
        }
        .filter-form button {
            padding: 8px 15px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            min-width: 80px; /* 按钮最小宽度 */
        }
        .filter-form button:hover {
            background-color: #0056b3;
        }

        .log-table { width: 100%; border-collapse: collapse; margin-top: 20px; }
        .log-table th, .log-table td { border: 1px solid #ddd; padding: 10px; text-align: left; vertical-align: top; }
        .log-table th { background-color: #f2f2f2; font-weight: bold; }
        .log-table tr:nth-child(even) { background-color: #f9f9f9; }
        .log-table .status-success { color: green; }
        .log-table .status-fail { color: red; background-color: #ffe0e0; } /* 突出显示失败的行 */
        .log-table td:nth-child(2) { word-break: break-all; } /* URL 列自动换行 */

        .details-popup {
            display: none;
            position: fixed;
            z-index: 1000;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            overflow: auto;
            background-color: rgba(0,0,0,0.4);
        }
        .details-popup-content {
            background-color: #fefefe;
            margin: 15% auto;
            padding: 20px;
            border: 1px solid #888;
            width: 80%;
            max-width: 700px;
            border-radius: 8px;
            position: relative;
        }
        .details-popup-close {
            color: #aaa;
            float: right;
            font-size: 28px;
            font-weight: bold;
        }
        .details-popup-close:hover,
        .details-popup-close:focus {
            color: black;
            text-decoration: none;
            cursor: pointer;
        }
        .details-popup pre {
            background-color: #eee;
            padding: 10px;
            border-radius: 4px;
            overflow-x: auto;
            white-space: pre-wrap;
            word-break: break-all;
        }
        .pagination { text-align: center; margin-top: 20px; }
        .pagination a { display: inline-block; padding: 8px 12px; margin: 0 5px; border: 1px solid #007bff; border-radius: 4px; text-decoration: none; color: #007bff; }
        .pagination a:hover { background-color: #e0f2ff; }
        .pagination span { display: inline-block; padding: 8px 12px; margin: 0 5px; background-color: #007bff; color: white; border-radius: 4px; }
    </style>
</head>
<body>
<div class="container">
    <h1>完整监控日志 - MySQL数据库</h1>
    <div class="back-link">
        <p><a href="index.php">← 返回监控面板</a></p>
    </div>

    <div class="filter-form">
        <form action="" method="get" style="display: flex; flex-wrap: wrap; gap: 15px; align-items: flex-end;">
            <div>
                <label for="start_date">开始日期:</label>
                <input type="date" id="start_date" name="start_date" value="<?php echo $startDate; ?>">
            </div>
            <div>
                <label for="end_date">结束日期:</label>
                <input type="date" id="end_date" name="end_date" value="<?php echo $endDate; ?>">
            </div>
            <div>
                <label for="domain">筛选域名:</label>
                <input type="text" id="domain" name="domain" value="<?php echo $domainFilter; ?>" placeholder="例如: example.com">
            </div>
            <div>
                <label for="status_code">状态码 (逗号分隔):</label>
                <input type="text" id="status_code" name="status_code" value="<?php echo $statusCodeFilter; ?>" placeholder="例如: 200,404">
            </div>
            <button type="submit">筛选</button>
        </form>
    </div>

    <table class="log-table">
        <thead>
        <tr>
            <th>时间</th>
            <th>URL</th>
            <th>状态码</th>
            <th>状态信息</th>
            <th>响应时间 (秒)</th>
            <th>详情</th>
        </tr>
        </thead>
        <tbody>
        <?php if (empty($logs)): ?>
            <tr><td colspan="6">没有找到符合条件的日志记录。</td></tr>
        <?php else: ?>
            <?php foreach ($logs as $log):
                $isSuccess = ($log['status_code'] >= 200 && $log['status_code'] < 300);
                $rowClass = $isSuccess ? '' : 'status-fail'; // 对非 2xx 状态的行应用失败样式
                ?>
                <tr class="<?php echo $rowClass; ?>">
                    <td><?php echo htmlspecialchars($log['log_time']); ?></td>
                    <td><?php echo htmlspecialchars($log['url']); ?></td>
                    <td><?php echo htmlspecialchars($log['status_code']); ?></td>
                    <td>
                        <?php if ($isSuccess): ?>
                            <span class="status-success">🟢 <?php echo htmlspecialchars($log['status_message']); ?></span>
                        <?php else: ?>
                            <span class="status-fail">🔴 <?php echo htmlspecialchars($log['status_message']); ?></span>
                        <?php endif; ?>
                    </td>
                    <td><?php echo htmlspecialchars(sprintf("%.4f", $log['response_time'])); ?></td>
                    <td>
                        <?php
                        // 确保 JSON 是有效的，并且不是空 JSON 对象
                        $detailsJson = $log['details'];
                        $hasDetails = !empty($detailsJson) && $detailsJson !== '{}';
                        ?>
                        <?php if ($hasDetails): ?>
                            <button onclick="showDetails('<?php echo htmlspecialchars(addslashes($detailsJson)); ?>')">查看详情</button>
                        <?php else: ?>
                            无
                        <?php endif; ?>
                    </td>
                </tr>
            <?php endforeach; ?>
        <?php endif; ?>
        </tbody>
    </table>

    <div class="pagination">
        <?php
        // 构建分页链接参数
        $filterParams = "&domain=" . urlencode($domainFilter)
            . "&status_code=" . urlencode($statusCodeFilter)
            . "&start_date=" . urlencode($startDate)
            . "&end_date=" . urlencode($endDate);

        if ($currentPage > 1): ?>
            <a href="?page=<?php echo $currentPage - 1; ?><?php echo $filterParams; ?>">上一页</a>
        <?php endif; ?>
        <span>页 <?php echo $currentPage; ?> / <?php echo $totalPages; ?></span>
        <?php if ($currentPage < $totalPages): ?>
            <a href="?page=<?php echo $currentPage + 1; ?><?php echo $filterParams; ?>">下一页</a>
        <?php endif; ?>
    </div>
</div>

<div id="detailsPopup" class="details-popup">
    <div class="details-popup-content">
        <span class="details-popup-close" onclick="closeDetails()">&times;</span>
        <h2>详细信息</h2>
        <pre id="detailsContent"></pre>
    </div>
</div>

<script>
    const detailsPopup = document.getElementById('detailsPopup');
    const detailsContent = document.getElementById('detailsContent');

    function showDetails(detailsJsonString) {
        try {
            // 解析 JSON 字符串，然后再次字符串化以美化输出
            detailsContent.textContent = JSON.stringify(JSON.parse(detailsJsonString), null, 2);
        } catch (e) {
            detailsContent.textContent = "解析详细信息时出错: " + detailsJsonString;
            console.error("JSON 解析错误:", e, detailsJsonString);
        }
        detailsPopup.style.display = 'block';
    }

    function closeDetails() {
        detailsPopup.style.display = 'none';
        detailsContent.textContent = '';
    }

    // 点击模态框外部关闭
    window.onclick = function(event) {
        if (event.target == detailsPopup) {
            closeDetails();
        }
    }
</script>
</body>
</html>
